/****************************************************
	文件：SchemeToolsEditor.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/9/20 10:59:26
	功能：配置表转换器
*****************************************************/

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using System.Text;

namespace HTUtility
{
    public class SchemeToolsEditor : EditorWindow
    {
        #region Consts
        /// <summary>
        /// 配置表根目录
        /// </summary>
        public const string SCHEME_FOLDER_PATH = "Assets/HTUtility/11-SchemeTools/Example/";
        public const string EXCEL_FOLDER_NAME = "Excel/";
        public const string CSV_FOLDER_NAME = "Csv/";
        public const string XML_FOLDER_NAME = "Xml/";
        public const string JSON_FOLDER_NAME = "Json/";
        public const string LUA_FOLDER_NAME = "Lua/";
        public const string BINARY_FOLDER_NAME = "Binary/";
        public const string CSHARP_FOLDER_NAME = "CSharp/";

        public static string ExcelFolderPath = SCHEME_FOLDER_PATH + EXCEL_FOLDER_NAME;
        public static string CsvFolderPath = SCHEME_FOLDER_PATH + CSV_FOLDER_NAME;
        public static string XmlFolderPath = SCHEME_FOLDER_PATH + XML_FOLDER_NAME;
        public static string JsonFolderPath = SCHEME_FOLDER_PATH + JSON_FOLDER_NAME;
        public static string LuaFolderPath = SCHEME_FOLDER_PATH + LUA_FOLDER_NAME;
        public static string BinaryFolderPath = SCHEME_FOLDER_PATH + BINARY_FOLDER_NAME;
        public static string CSharpFolderPath = SCHEME_FOLDER_PATH + CSHARP_FOLDER_NAME;
        #endregion

        /// <summary>
        /// 窗口实例
        /// </summary>
        private static EditorWindow mWnd;
        /// <summary>
        /// Excel文件路径列表
        /// </summary>
        private static List<string> mExcelPathList;
        /// <summary>
        /// 项目路径
        /// </summary>
        private static string mRootPath;
        /// <summary>
        /// 滚动窗口初始位置
        /// </summary>
        private static Vector2 mScrollPos;
        /// <summary>
        /// 是否生成C#
        /// </summary>
        private static bool mGenerateCSharp;

        /// <summary>
        /// 是否生成C#
        /// </summary>
        public static bool GenerateCSharp
        {
            get
            {
                return mOutOptionIndex == 4 ? true : mGenerateCSharp; //Bytes需要先生成CSharp
            }
            set
            {
                mGenerateCSharp = value;
            }
        }

        /// <summary>
        /// 编码格式索引
        /// </summary>
        private static int mEncodingIndex;
        /// <summary>
        /// 编码格式
        /// </summary>
        private static string[] mEncodingArray = new string[] { "UTF-8", "GB2312" };
        /// <summary>
        /// 当前选中的编码格式
        /// </summary>
        private static Encoding mCurEncoding
        {
            get
            {
                return Encoding.GetEncoding(mEncodingArray[mEncodingIndex]);
            }
        }
        /// <summary>
        /// 输出格式索引
        /// </summary>
        private static int mOutOptionIndex;
        /// <summary>
        /// 输出格式
        /// </summary>
        private static string[] mOutOptionArray = new string[] { "Csv", "Xml", "Json", "Lua", "Bytes" };
        /// <summary>
        /// 当前选中的输出格式
        /// </summary>
        private static string mCurOutOption
        {
            get
            {
                return "." + mOutOptionArray[mOutOptionIndex].ToLower();
            }
        }

        [MenuItem("HTUtility/8.SchemeToolsEditor", false, 8)]
        private static void MenuClick()
        {
            Init();
            LoadExcel();
            mWnd.Show();
        }
        private void OnGUI()
        {
            DrawOptions();
            DrawExport();
        }
        private void OnSelectionChange()
        {
            mWnd.Show();
            LoadExcel();
            mWnd.Repaint();
        }

        private static void Init()
        {
            mWnd = GetWindow<SchemeToolsEditor>("配置表工具");
            mRootPath = Application.dataPath; // E:/Work/Gitee/HTUtility/Assets
            mRootPath = mRootPath.Substring(0, mRootPath.LastIndexOf("/")); // E:/Work/Gitee/HTUtility
            mScrollPos = new Vector2(mWnd.position.x, mWnd.position.y - 30);
            mExcelPathList = new List<string>();
        }

        /// <summary>
        /// 绘制配置
        /// </summary>
        private void DrawOptions()
        {
            GUILayout.Label(" 设置", new GUIStyle
            {
                fontSize = 16,
                fontStyle = FontStyle.Bold,
            });
            GUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("输出格式类型:", GUILayout.Width(85));
            mOutOptionIndex = EditorGUILayout.Popup(mOutOptionIndex, mOutOptionArray, GUILayout.Width(125));
            GUILayout.EndHorizontal();

            GUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("编码类型:", GUILayout.Width(85));
            mEncodingIndex = EditorGUILayout.Popup(mEncodingIndex, mEncodingArray, GUILayout.Width(125));
            GUILayout.EndHorizontal();
        }

        /// <summary>
        /// 绘制转换
        /// </summary>
        private void DrawExport()
        {
            if (mExcelPathList == null) return;
            GUILayout.Label(" 转换", new GUIStyle
            {
                fontSize = 16,
                fontStyle = FontStyle.Bold,
            });
            if (mExcelPathList.Count < 1)
            {
                EditorGUILayout.LabelField("没有Excel文件被选中!");
                return;
            }
            EditorGUILayout.LabelField($"下列 Excel 将被转换为 {mOutOptionArray[mOutOptionIndex]} ：");
            GUILayout.BeginVertical();
            GenerateCSharp = GUILayout.Toggle(GenerateCSharp, "生成CSharp");
            mScrollPos = GUILayout.BeginScrollView(mScrollPos, false, true, GUILayout.Height(300));
            foreach (string excelPath in mExcelPathList)
            {
                GUILayout.BeginHorizontal();
                GUILayout.Toggle(true, excelPath);
                GUILayout.EndHorizontal();
            }
            GUILayout.EndScrollView();
            GUILayout.EndVertical();
            //转换
            if (GUILayout.Button("确定"))
            {
                if (mGenerateCSharp) Generate();
                Convert();
            }
        }

        /// <summary>
        /// 加载Excel，读取Excel文件路径
        /// </summary>
        private static void LoadExcel()
        {
            if (mExcelPathList == null)
                mExcelPathList = new List<string>();
            mExcelPathList.Clear();
            //获取选中的对象
            UnityEngine.Object[] selectionArray = Selection.objects;
            //判断是否有对象被选中
            if (selectionArray == null || selectionArray.Length == 0)
                return;
            HashSet<string> hashSet = new HashSet<string>(); //过滤重复文件路径
            //遍历每一个对象判断不是Excel文件
            foreach (UnityEngine.Object obj in selectionArray)
            {
                string objPath = AssetDatabase.GetAssetPath(obj);
                if (HelperUtil.IsFolder(objPath))
                {
                    List<string> itemPathLst = HelperUtil.GetFilesInFolder(objPath);
                    for (int i = 0; i < itemPathLst.Count; i++)
                    {
                        itemPathLst[i] = itemPathLst[i].Replace('\\', '/').Replace(mRootPath + "/", string.Empty);
                        hashSet.Add(itemPathLst[i]);
                    }
                }
                else
                {
                    hashSet.Add(objPath);
                }
            }
            mExcelPathList = HelperUtil.FilterFileListBySuffix(hashSet, ".xlsx");
        }
        /// <summary>
        /// 转换Excel文件
        /// </summary>
        private static void Convert()
        {
            for (int i = 0; i < mExcelPathList.Count; i++)
            {
                string excelPath = mRootPath + "/" + mExcelPathList[i];
                EditorUtility.DisplayProgressBar($"Excel To {mOutOptionArray[mOutOptionIndex]}", $"正在转换：{excelPath}", 1.0f * (i + 1) / mExcelPathList.Count);
                ExcelHandler handler = ExcelKits.Instance.Create(excelPath);
                string outPath = GetOutPath(excelPath);
                switch (mOutOptionIndex)
                {
                    case 0:
                        handler.ToCsv(outPath, mCurEncoding);
                        break;
                    case 1:
                        handler.ToXml(outPath, mCurEncoding);
                        break;
                    case 2:
                        handler.ToJson(outPath, mCurEncoding);
                        break;
                    case 3:
                        handler.ToLua(outPath, mCurEncoding);
                        break;
                    case 4:
                        //handler.ToBinary(outPath);
                        EditorUtil.SubscribeCompileFinishedCallBack("ConvertAfterCompile", "HTUtility", "SchemeToolsEditor");
                        EditorUtility.ClearProgressBar();
                        AssetDatabase.Refresh();
                        mWnd.Close();
                        return;
                }
            }
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
            Debug.LogFormat("成功转换 {0} 个 Excel 为 {1}", mExcelPathList.Count, mOutOptionArray[mOutOptionIndex]);
            mWnd.Close();
        }
        public static void ConvertAfterCompile()
        {
            Init();
            LoadExcel();
            mWnd.Show();
            for (int i = 0; i < mExcelPathList.Count; i++)
            {
                string excelPath = mRootPath + "/" + mExcelPathList[i];
                EditorUtility.DisplayProgressBar($"Excel To Binary", $"正在转换：{excelPath}", 1.0f * (i + 1) / mExcelPathList.Count);
                ExcelHandler handler = ExcelKits.Instance.Create(excelPath);
                string outPath = excelPath.Replace(".xlsx", ".bytes").Replace(EXCEL_FOLDER_NAME, BINARY_FOLDER_NAME);
                handler.ToBinary(outPath);
            }
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
            Debug.LogFormat("成功转换 {0} 个 Excel 为 Binary", mExcelPathList.Count);
            mWnd.Close();
        }
        /// <summary>
        /// 生成 CSharp
        /// </summary>
        private static void Generate()
        {
            bool isEditScriptTemplate = ScriptTemplateData.IsEditScriptTemplate;
            ScriptTemplateData.IsEditScriptTemplate = false;
            for (int i = 0; i < mExcelPathList.Count; i++)
            {
                string excelPath = mRootPath + "/" + mExcelPathList[i];
                EditorUtility.DisplayProgressBar($"Excel To CSharp", $"正在转换：{excelPath}", 1.0f * (i + 1) / mExcelPathList.Count);
                ExcelHandler handler = ExcelKits.Instance.Create(excelPath);
                string outPath = excelPath.Replace(".xlsx", ".cs").Replace(EXCEL_FOLDER_NAME, CSHARP_FOLDER_NAME);
                handler.ToCSharp(outPath, mCurEncoding);
            }
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();
            ScriptTemplateData.IsEditScriptTemplate = isEditScriptTemplate;
            Debug.LogFormat("成功生成 {0} 个 CSharp", mExcelPathList.Count);
        }
        /// <summary>
        /// 获取输出路径
        /// </summary>
        /// <returns></returns>
        private static string GetOutPath(string excelPath)
        {
            string outPath = string.Empty;
            excelPath = excelPath.Replace(".xlsx", mCurOutOption);
            switch (mOutOptionIndex)
            {
                case 0:
                    outPath = excelPath.Replace(EXCEL_FOLDER_NAME, CSV_FOLDER_NAME);
                    break;
                case 1:
                    outPath = excelPath.Replace(EXCEL_FOLDER_NAME, XML_FOLDER_NAME);
                    break;
                case 2:
                    outPath = excelPath.Replace(EXCEL_FOLDER_NAME, JSON_FOLDER_NAME);
                    break;
                case 3:
                    outPath = excelPath.Replace(EXCEL_FOLDER_NAME, LUA_FOLDER_NAME);
                    break;
                case 4:
                    outPath = excelPath.Replace(EXCEL_FOLDER_NAME, BINARY_FOLDER_NAME);
                    break;
            }
            return outPath;
        }
    }
}
